package com.lancoo.znbkxx.teacher.viewmodel

import android.app.Application
import android.media.MediaMetadataRetriever
import android.os.Environment
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.lancoo.cpbase.authentication.base.CurrentUser
import com.lancoo.znbkxx.teacher.Ext
import com.lancoo.znbkxx.teacher.Ext.Companion.AK
import com.lancoo.znbkxx.teacher.Ext.Companion.BASE_URL_COMMENT
import com.lancoo.znbkxx.teacher.Ext.Companion.COURSE_CLASSID
import com.lancoo.znbkxx.teacher.Ext.Companion.CNTOBSINFO
import com.lancoo.znbkxx.teacher.Ext.Companion.SCHOOLID
import com.lancoo.znbkxx.teacher.Ext.Companion.SK
import com.lancoo.znbkxx.teacher.Ext.Companion.bucketName
import com.lancoo.znbkxx.teacher.Ext.Companion.endPoint
import com.lancoo.znbkxx.teacher.Ext.Companion.executeResponse
import com.lancoo.znbkxx.teacher.base.BaseViewModel
import com.lancoo.znbkxx.teacher.model.data.*
import com.lancoo.znbkxx.teacher.model.repository.CommentsRepository
import com.lancoo.znbkxx.teacher.utils.FileUtils
import com.luck.picture.lib.entity.LocalMedia
import com.obs.services.ObsClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.asRequestBody
import org.json.JSONArray
import org.json.JSONObject
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.net.HttpURLConnection
import java.net.URL
import java.util.concurrent.TimeUnit


/**
 * @author : Admin
 * @date   : 2019/8/5 17:40
 * @desc   :
 */
class HardSolutionViewModel(application: Application) : BaseViewModel(application) {
    val mediaList = MutableLiveData<MutableList<LocalMedia>>()
    val hardSolution = MutableLiveData<HardItemSolution>()
    val answerDetail = MutableLiveData<MutableList<AnswerDetail>>()
    val classicalList = MutableLiveData<MutableList<Classical>>()
    val knowledgeInfo = MutableLiveData<KnowledgeInfo>()
    val audioPath = MutableLiveData<String>()
    val klgCode = MutableLiveData<String>()
    val mErrorMsg = MutableLiveData<String>()
    val videoMap = MutableLiveData<HashMap<String, Any>>()
    val answerSkill = MutableLiveData<SkillListBean>()
    val answerSkillComment = MutableLiveData<SkillCommentInfoBean>()
    val skillList = MutableLiveData<MutableList<AnsweringSkill>>()
    val expandQues = MutableLiveData<MutableList<RecQuesID>>()
    val classicWrongQue = MutableLiveData<MutableList<ClassicWrongQue>>()
    val answerSkillList = MutableLiveData<MutableList<AnsweringSkill>>()
    val wrongCommentInfo = MutableLiveData<WrongCommentInfo>()
    val resultInfo = MutableLiveData<ResultInfo>()
    val tkModels = MutableLiveData<MutableList<TkModel>>()
    private val repository by lazy { CommentsRepository() }
    private val obs by lazy { ObsClient(AK, SK, endPoint) }
    val success = MutableLiveData<Int>()


    fun getHardItemSolution(TID: String, CourseClassID: String, SchoolID: String, Token: String,
                            QuesID: String, PaperID: String, SetID: String, StageNo: String) {
        launch {
            val result = repository.getHardItemSolution(TID, CourseClassID, SchoolID, Token, QuesID,
                    PaperID, SetID, StageNo)
            executeResponse(result, { hardSolution.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun upLoad(zsdList: MutableList<ImportKlg>, classicalList: MutableList<Classical>,
               list: MutableList<LocalMedia>, tempList: MutableList<LocalMedia>, content: String,
               PaperName: String, state: Int) {
        launch {
            val arrayImg = JSONArray()
            val audioList = mutableListOf<String>()
            var realVideoPath = ""
            if (list.size > 0) {
                withContext(Dispatchers.Default) {
                    list.forEach {
                        val sbImg = JSONObject()
                        val mediaType = when {
                            it.mimeType.contains("image") -> 1
                            it.mimeType.contains("video") -> 2
                            else -> 3
                        }
                        var isSame = false
                        tempList.forEach { local ->
                            if (local.path == it.path) isSame = true
                        }
                        if (!isSame) {
                            val file: File = if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.LOLLIPOP) {
                                File(if (it.isCompressed) it.compressPath else it.androidQToPath)
                            } else {
                                File(if (it.isCompressed) it.compressPath else it.realPath
                                        ?: it.path)
                            }
                            withContext(Dispatchers.IO) {
                                if (mediaType == 1) {
                                    val result = obs.putObject(bucketName,
                                            "${CNTOBSINFO!!.SysOBSRelativePath}/pictures/${CurrentUser.getSchoolID()}/${file.name}",
                                            file)
                                    if (result.statusCode == 200) {
                                        sbImg.put("src", result.objectKey)
                                        arrayImg.put(sbImg)
                                    }else{
                                        mErrorMsg.value="obs上传失败，请重试"
                                        return@withContext
                                    }
                                } else {
                                    val result = obs.putObject(bucketName,
                                            "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${CurrentUser.getSchoolID()}/${file.name}",
                                            file)
                                    if (result.statusCode == 200) {
                                        if (mediaType == 2) {
                                            realVideoPath = result.objectKey
                                        } else {
                                            audioList.add(result.objectKey)
                                        }
                                    }else{
                                        mErrorMsg.value="obs上传失败，请重试"
                                        return@withContext
                                    }
                                }
                            }
                        } else {
                            if (mediaType == 1) {
                                sbImg.put("src",
                                        "${CNTOBSINFO!!.SysOBSRelativePath}/pictures/${CurrentUser.getSchoolID()}${it.path.let {
                                            it.substring(it.lastIndexOf("/"))
                                        }}")
                                arrayImg.put(sbImg)
                            } else {
                                if (mediaType == 2) {
                                    realVideoPath = "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${CurrentUser.getSchoolID()}${it.path.let {
                                        it.substring(it.lastIndexOf("/"))
                                    }}"
                                } else {
                                    val audio = "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${CurrentUser.getSchoolID()}${it.path.let {
                                        it.substring(it.lastIndexOf("/"))
                                    }}"
                                    audioList.add(audio)
                                }
                            }
                        }
                    }
                }
            }
            val imgPath = if (arrayImg.length() > 0) arrayImg.toString() else ""
            val audioPath = if (audioList.isNotEmpty()) audioList.joinToString("|") else ""

            val result = repository.saveHardItemSolution(CurrentUser.getToken(), CurrentUser.getUserID(),
                    hardSolution.value!!.TkModel.QuesID, COURSE_CLASSID, CurrentUser.getSchoolID(),
                    content, audioPath, realVideoPath, imgPath, classicalList, PaperName, state,
                    zsdList)
            executeResponse(result, { success.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun upLoadOneOnOne(zsdList: MutableList<ImportKlg>, classicalList: MutableList<Classical>,
                       list: MutableList<LocalMedia>, tempList: MutableList<LocalMedia>,
                       content: String,
                       PaperName: String, state: Int) {
        launch {
            val arrayImg = JSONArray()
            val audioList = mutableListOf<String>()
            var realVideoPath = ""
            if (list.size > 0) {
                withContext(Dispatchers.Default) {
                    list.forEach {
                        val sbImg = JSONObject()
                        val mediaType = when {
                            it.mimeType.contains("image") -> 1
                            it.mimeType.contains("video") -> 2
                            else -> 3
                        }
                        var isSame = false
                        tempList.forEach { local ->
                            if (local.path == it.path) isSame = true
                        }
                        if (!isSame) {
                            val file: File = if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.LOLLIPOP) {
                                File(if (it.isCompressed) it.compressPath else it.androidQToPath)
                            } else {
                                File(if (it.isCompressed) it.compressPath else it.realPath
                                        ?: it.path)
                            }
                            withContext(Dispatchers.IO) {
                                if (mediaType == 1) {
                                    val result = obs.putObject(bucketName,
                                            "${CNTOBSINFO!!.SysOBSRelativePath}/pictures/${SCHOOLID}/${file.name}",
                                            file)
                                    if (result.statusCode == 200) {
                                        sbImg.put("src", result.objectKey)
                                        arrayImg.put(sbImg)
                                    }else{
                                        mErrorMsg.value="obs上传失败，请重试"
                                        return@withContext
                                    }
                                } else {
                                    val result = obs.putObject(bucketName,
                                            "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${SCHOOLID}/${file.name}",
                                            file)
                                    if (result.statusCode == 200) {
                                        if (mediaType == 2) {
                                            realVideoPath = result.objectKey
                                        } else {
                                            audioList.add(result.objectKey)
                                        }
                                    }else{
                                        mErrorMsg.value="obs上传失败，请重试"
                                        return@withContext
                                    }
                                }
                            }
                        } else {
                            if (mediaType == 1) {
                                sbImg.put("src",
                                        "${CNTOBSINFO!!.SysOBSRelativePath}/pictures/${SCHOOLID}${it.path.let {
                                            it.substring(it.lastIndexOf("/"))
                                        }}")
                                arrayImg.put(sbImg)
                            } else {
                                if (mediaType == 2) {
                                    realVideoPath = "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${SCHOOLID}${it.path.let {
                                        it.substring(it.lastIndexOf("/"))
                                    }}"
                                } else {
                                    val audio = "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${SCHOOLID}${it.path.let {
                                        it.substring(it.lastIndexOf("/"))
                                    }}"
                                    audioList.add(audio)
                                }
                            }
                        }
                    }
                }
            }
            val imgPath = if (arrayImg.length() > 0) arrayImg.toString() else ""
            val audioPath = if (audioList.isNotEmpty()) audioList.toString() else ""


            val result = repository.saveWrongSolution(CurrentUser.getToken(), CurrentUser.getUserID(),
                    Ext.STU_ID, hardSolution.value!!.TkModel.QuesID, COURSE_CLASSID, SCHOOLID,
                    content, audioPath, realVideoPath, imgPath, classicalList, PaperName, state,
                    zsdList)
            executeResponse(result, { resultInfo.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun saveAnswerSkillSolution(content: String, list: MutableList<LocalMedia>,
                                tempList: MutableList<LocalMedia>, StuID: String, flag: Int) {
        launch {
            val arrayImg = JSONArray()
            val audioList = mutableListOf<String>()
            var realVideoPath = ""
            if (list.size > 0) {
                withContext(Dispatchers.Default) {
                    list.forEach {
                        val sbImg = JSONObject()
                        val mediaType = when {
                            it.mimeType.contains("image") -> 1
                            it.mimeType.contains("video") -> 2
                            else -> 3
                        }
                        var isSame = false
                        tempList.forEach { local ->
                            if (local.path == it.path) isSame = true
                        }
                        if (!isSame) {
                            val file: File = if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.LOLLIPOP) {
                                File(if (it.isCompressed) it.compressPath else it.androidQToPath)
                            } else {
                                File(if (it.isCompressed) it.compressPath else it.realPath
                                        ?: it.path)
                            }
                            withContext(Dispatchers.IO) {
                                if (mediaType == 1) {
                                    val result = obs.putObject(bucketName,
                                            "${CNTOBSINFO!!.SysOBSRelativePath}/pictures/${SCHOOLID}/${file.name}",
                                            file)
                                    if (result.statusCode == 200) {
                                        sbImg.put("src", result.objectKey)
                                        arrayImg.put(sbImg)
                                    }
                                } else {
                                    val result = obs.putObject(bucketName,
                                            "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${SCHOOLID}/${file.name}",
                                            file)
                                    if (result.statusCode == 200) {
                                        if (mediaType == 2) {
                                            realVideoPath = result.objectKey
                                        } else {
                                            audioList.add(result.objectKey)
                                        }
                                    }
                                }
                            }
                        } else {
                            if (mediaType == 1) {
                                sbImg.put("src",
                                        "${CNTOBSINFO!!.SysOBSRelativePath}/pictures/${SCHOOLID}${it.path.let {
                                            it.substring(it.lastIndexOf("/"))
                                        }}")
                                arrayImg.put(sbImg)
                            } else {
                                if (mediaType == 2) {
                                    realVideoPath = "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${SCHOOLID}${it.path.let {
                                        it.substring(it.lastIndexOf("/"))
                                    }}"
                                } else {
                                    val audio = "${CNTOBSINFO!!.SysOBSRelativePath}/audio/${SCHOOLID}${it.path.let {
                                        it.substring(it.lastIndexOf("/"))
                                    }}"
                                    audioList.add(audio)
                                }
                            }
                        }
                    }
                }
            }
            val imgPath = if (arrayImg.length() > 0) arrayImg.toString() else ""
            val audioPath = if (audioList.isNotEmpty()) audioList.joinToString("|") else ""
            answerSkillComment.value?.let {
                it.SolutionContent = content
                it.PicturePath = imgPath
                it.AudioPath = audioPath
                it.VideoPath = realVideoPath
            }
            val result = repository.saveAnswerSkillSolution(answerSkillComment.value!!, StuID, flag)
            executeResponse(result, { resultInfo.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    private fun upLoad2Server(type: Int, file: File?, jsonObject: JSONObject,
                              jsonArray: JSONArray) {
        val client = OkHttpClient()
        var url: String? = null
        val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM)
        val body: RequestBody
        if (file != null) {
            when (type) {
                1 -> {
                    body = file.asRequestBody("image/*".toMediaTypeOrNull())
                    url = "/W_ZNBK_ImgUploadImage"
                }
                2 -> {
                    body = file.asRequestBody("video/*".toMediaTypeOrNull())
                    url = "/W_ZNBK_ImgUpLoadAudio"
                }
                else -> {
                    body = file.asRequestBody("audio/*".toMediaTypeOrNull())
                    url = "/W_ZNBK_ImgUpLoadAudio"
                }
            }
            val filename = file.name
            requestBody.addFormDataPart("file", filename, body)
        }
        val request = Request.Builder().url(BASE_URL_COMMENT + url).post(requestBody.build())
                .build()
        val json = client.newBuilder().readTimeout(5000, TimeUnit.MILLISECONDS).build()
                .newCall(request).execute().body?.string()
        val jsArray = JSONArray(json)
        val path = jsArray.getJSONObject(0).getString("RelativePath")
        jsonObject.put("src", path)
        jsonArray.put(jsonObject)
    }

    fun getClassicalList(Token: String, SchoolID: String, QuesID: String, StageNo: String,
                         SelectedList: MutableList<Classical>, TID: String) {
        launch {
            val result = repository.getClassicalList(Token, SchoolID, QuesID, StageNo, SelectedList,
                    TID)
            executeResponse(result, { classicalList.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getSelectedClassicalList(Token: String, SchoolID: String, QuesID: String, StageNo: String,
                                 SelectedList: MutableList<Classical>, TID: String) {
        launch {
            val result = repository.getSelectedClassicalList(Token, SchoolID, QuesID, StageNo,
                    SelectedList, TID)
            executeResponse(result, { classicalList.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getZSDCourseware(QuesID: String) {
        launch {
            val result = repository.getZSDCourseware(QuesID)
            executeResponse(result, { knowledgeInfo.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getStuAnswerList(QuesID: String) {
        launch {
            val result = repository.getStuAnswerList(QuesID)
            executeResponse(result, { answerDetail.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getKlgCode(UniqueCode: String) {
        launch {
            val result = repository.getKlgCode(UniqueCode)
            executeResponse(result, { klgCode.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun downLoadAudio(path: String, fileName: String) {
        launch {
            withContext(Dispatchers.IO) {
                val url = URL(path)
                val con = url.openConnection() as HttpURLConnection
                con.readTimeout = 5000
                con.connectTimeout = 5000
                con.setRequestProperty("Charset", "UTF-8")
                con.requestMethod = "GET"
                if (con.responseCode == 200) {
                    val inputStream = con.inputStream //获取输入流
                    var fileOutputStream: FileOutputStream? = null //文件输出流
                    if (inputStream != null) {
                        val fileUtils = FileUtils(
                                Environment.getExternalStorageDirectory().absolutePath + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/")
                        fileOutputStream = FileOutputStream(fileUtils.createFile(
                                Environment.getExternalStorageDirectory().absolutePath + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/",
                                fileName))
                        val buf = ByteArray(1024)
                        var ch: Int
                        while (inputStream.read(buf).also { ch = it } != -1) {
                            fileOutputStream.write(buf, 0, ch) //将获取到的流写入文件中
                        }
                    }
                    if (fileOutputStream != null) {
                        fileOutputStream.flush()
                        fileOutputStream.close()
                    }
                }
            }
            audioPath.value = Environment.getExternalStorageDirectory().absolutePath + "/Android/data/com.lancoo.znbkxx.teacher/" + "files/audio/" + fileName
        }
    }

    fun saveVideoInfo(path: String) {
        launch {
            val map = hashMapOf<String, Any>()
            withContext(Dispatchers.IO) {
                val retriever = MediaMetadataRetriever()
                if (path.contains("http")) {
                    retriever.setDataSource(path, HashMap())
                } else {
                    val inputStream = FileInputStream(File(path).absolutePath)
                    retriever.setDataSource(inputStream.fd)
                }
                //获得第一帧图片
                val bitmap = retriever.frameAtTime
                val videoTimes = retriever.extractMetadata(
                        MediaMetadataRetriever.METADATA_KEY_DURATION).toLong()
                retriever.release()
                map["bitmap"] = bitmap
                map["videoTimes"] = videoTimes
            }
            videoMap.value = map
        }
    }

    fun getAnswerSkill(StuID: String, PageIndex: Int, PageNum: Int) {
        launch {
            val result = repository.getAnswerSkill(StuID, PageIndex, PageNum)
            executeResponse(result, { answerSkill.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getQTypeComments(StuID: String, TypeNo: String, GenreID: String) {
        launch {
            val result = repository.getQTypeComments(StuID, TypeNo, GenreID)
            executeResponse(result, {
                answerSkillComment.value = result.Data
                val gson = Gson().toJson(result.Data.AnsweringSkills)
                skillList.value = Gson().fromJson<MutableList<AnsweringSkill>>(gson,
                        object : TypeToken<MutableList<AnsweringSkill>>() {}.type)
            },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getResourceQuesInfo(QuesIDs: String, StartIndex: Int, IsSerial: Boolean,
                            IsReplace: Boolean) {
        launch {
            val result = repository.getResourceQuesInfo(QuesIDs, StartIndex, IsSerial, IsReplace)
            executeResponse(result, { tkModels.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getChangeExpandPracticeQues(StuID: String, TypeNo: String, GenreID: String) {
        launch {
            val result = repository.getChangeExpandPracticeQues(StuID, TypeNo, GenreID)
            executeResponse(result, { expandQues.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getChangeClassicWrongQues(StuID: String, TypeNo: String, GenreID: String) {
        launch {
            val result = repository.getChangeClassicWrongQues(StuID, TypeNo, GenreID)
            executeResponse(result, { classicWrongQue.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getAnswerSkillList(TypeNo: String, GenreID: String) {
        launch {
            val result = repository.getAnswerSkillList(TypeNo, GenreID)
            executeResponse(result, { answerSkillList.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getWrongComment(StuID: String, PageIndex: Int,
                        PageNum: Int) {
        launch {
            val result = repository.getWrongComment(StuID, PageIndex, PageNum)
            executeResponse(result, { wrongCommentInfo.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }

    fun getWrongSolutionDetail(QuesID: String) {
        launch {
            val result = repository.getWrongSolutionDetail(QuesID)
            executeResponse(result, { hardSolution.value = result.Data },
                    { mErrorMsg.value = result.Message })
        }
    }
}